#include <jni.h>
#include <string>
#include <iostream>
#include <android/bitmap.h>
#include "android/log.h"

using namespace std;

void gaussBlur(int *, int, int, int);

#ifndef LOG_TAG
#define LOG_TAG "JNI_LOG" //Log 的 tag 名字
//定义各种类型 Log 的函数别名
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG ,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG ,__VA_ARGS__)
#endif

extern "C" { int updatePatch(int argc, char *argv[]); }

/*extern "C"
JNIEXPORT jint JNICALL
Java_com_zhibo_download_util_PatchUtil_patchUpdate(JNIEnv *env, jclass clazz, jstring oldApk_,
                                                   jstring newApk_, jstring patch_) {

    //相当于类型转换,转换成C/C++识别字符串
    const char *oldApk = env->GetStringUTFChars(oldApk_, 0);
    const char *newApk = env->GetStringUTFChars(newApk_, 0);
    const char *patch = env->GetStringUTFChars(patch_, 0);
    char *arr[4] = {
            "bsdiff",
            const_cast<char *>(oldApk),
            const_cast<char *>(newApk),
            const_cast<char *>(patch)};

    int result = updatePatch(4, arr);

    //释放指针
    env->ReleaseStringUTFChars(oldApk_, oldApk);
    env->ReleaseStringUTFChars(patch_, patch);
    env->ReleaseStringUTFChars(newApk_, newApk);
    return result;
}*/
extern "C"
JNIEXPORT jstring JNICALL
//参数2:如果java方法为静态方法 设置 class,如果是非静态的 设置object
Java_com_rlz_framemm_util_JniUtil_getJinMsg(JNIEnv *env, jclass clazz) {

    std::string msg = "JNI调佣 ";


    return env->NewStringUTF(msg.c_str());
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_rlz_framemm_util_JniUtil_concatString(JNIEnv *env, jclass clazz, jstring s1, jstring s2) {

    //jstring 转 char*
    const char *_s1 = env->GetStringUTFChars(s1, nullptr);
    const char *_s2 = env->GetStringUTFChars(s2, nullptr);

    const char *concatStr = "-新加入-";

    //申请一个地址空间
    char *news = (char *) (malloc(strlen(_s1) + strlen(concatStr) + strlen(_s2)));

    strcpy(news, _s1);
    strcat(news, concatStr);
    strcat(news, _s2);


    //释放内存
    env->ReleaseStringUTFChars(s1, _s1);
    env->ReleaseStringUTFChars(s2, _s2);


    //char 转为jstring 并返回
    return env->NewStringUTF(news);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_rlz_framemm_util_JniUtil_equalJni(JNIEnv *env, jclass clazz, jstring s1, jstring s2) {

    const char *_s1 = env->GetStringUTFChars(s1, nullptr);
    const char *_s2 = env->GetStringUTFChars(s2, nullptr);

    env->ReleaseStringUTFChars(s1, _s1);
    env->ReleaseStringUTFChars(s2, _s2);


    //返回值 如果 [小于]0 : s1 [小于]s2
    //返回值 如果 [大于]0 : s1 [大于]s2
    //返回值 如果 [等于]0 : s1 [等于]s2
    return strcmp(_s1, _s2);
}




extern "C"
JNIEXPORT jint JNICALL
Java_com_rlz_framemm_util_JniUtil_arraySum(JNIEnv *env, jclass clazz, jintArray arr) {
    //方式一   有危险  从Java数组中获取数组指针
    /*jint *_arr = env->GetIntArrayElements(arr, nullptr);

    int sum = 0;
    int len = env->GetArrayLength(arr);

    for (int i = 0; i < len; ++i) {
        sum += _arr[i];
    }

    env->ReleaseIntArrayElements(arr, _arr, 0);*/


    //方式二 推荐:
    int sum = 0;

    int len = env->GetArrayLength(arr);

    //动态申请内存空间
    jint *c_arr = static_cast<jint *>(malloc(len));

    //初始化数组元素内容为0
    memset(c_arr, 0, sizeof(jint) * len);

    //将Java数组中的元素 从 [0-arr.length]的位置拷贝到c_arr中
    env->GetIntArrayRegion(arr, 0, len, c_arr);

    for (int i = 0; i < len; ++i) {
        sum += c_arr[i];
    }

    //动态释放内存
    free(c_arr);

    return sum;
}


JNIEXPORT jstring sayHello(JNIEnv *env, jobject) {
    const char *hello = "这是sayHello方法";
    return env->NewStringUTF(hello);
}


extern "C"
JNIEXPORT void blur(JNIEnv *env, jobject, jobject bitmap) {
   /* //初始化bitmap 结构
    AndroidBitmapInfo info = {0};

    //初始化Bitmap数据指针
    int *data = nullptr;

    AndroidBitmap_getInfo(env, bitmap, &info);
    //锁定bitmap,获得指针
    AndroidBitmap_lockPixels(env, bitmap, (void **) &data);

    //调用高斯模糊方法,图像作为指针, 传入图片宽高和模糊半径
    gaussBlur(data, info.width, info.height, 80);

    //解锁
    AndroidBitmap_unlockPixels(env, bitmap);*/
}

JNINativeMethod method[] = {
        {"getStringFromCpp", "()Ljava/lang/String;",         (void *) sayHello},
        {"recycle",          "()V",                          (void *) JNI_OnUnload},
        {"handleBlur",       "(Landroid/graphics/Bitmap;)V", (void *) blur},
};

jint registerNativeMethod(JNIEnv *env) {
    jclass cl = env->FindClass("com/rlz/framemm/jni/MethodJni");
    if ((env->RegisterNatives(cl, method, sizeof(method) / sizeof(method[0]))) < 0) {
        return -1;
    }
    return 0;
}

jint unRegisterNativeMethod(JNIEnv *env) {
    jclass cl = env->FindClass("com/rlz/framemm/jni/MethodJni");
    env->UnregisterNatives(cl);
    const char *msg = "资源释放完成";
    LOGI("%s", msg);
    return 0;
}

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) {
        registerNativeMethod(env);
        return JNI_VERSION_1_6;
    } else if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) == JNI_OK) {
        registerNativeMethod(env);
        return JNI_VERSION_1_4;
    }
    return JNI_ERR;
}

JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) {
        unRegisterNativeMethod(env);
    } else if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) == JNI_OK) {
        unRegisterNativeMethod(env);
    }
}

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_rlz_framemm_jni_MethodJni_jniArr(JNIEnv *env, jobject thiz, jintArray arr, jint len) {

    if (arr == nullptr || len < 1)
        return nullptr;

    //转为Jint 数组的首值
    jint *_arr = env->GetIntArrayElements(arr, nullptr);

    for (int i = 0; i < len - 1; ++i) {
        for (int j = 0; j < len - i - 1; ++j) {
            if (_arr[j] > _arr[j + 1]) {
                int temp = _arr[j];
                _arr[j] = _arr[j + 1];
                _arr[j + 1] = temp;
            }
        }
    }


    //将_arr这个int *中值复制到jArray数组中
    env->SetIntArrayRegion(arr, 0, len, _arr);

    //释放内存
    free(_arr);
    return arr;
}